# -*- coding: utf-8 -*-
import copy
import random
from scrapy import Request
from scrapy.utils.project import get_project_settings

from zc_core.client.mongo_client import Mongo
from zc_core.model.items import Box
from zc_core.spiders.base import BaseSpider
from zc_core.dao.batch_dao import BatchDao
from cncecyc.rules import *
from zc_core.util.common import half_split_int_range
from cncecyc.utils.login import SeleniumLogin
from cncecyc.utils.item_helper import ItemHelper


class FullSpider(BaseSpider):
    name = 'full'
    custom_settings = {
        'CONCURRENT_REQUESTS': 12,
        # 'DOWNLOAD_DELAY': 0.1,
        'CONCURRENT_REQUESTS_PER_DOMAIN': 12,
        'CONCURRENT_REQUESTS_PER_IP': 12,
    }
    # 常用链接
    list_url = 'https://www.cncecyc.com/share-ecommerce/providerCommodity/selectCommodityList'
    # 常用链接
    item_url = 'https://www.cncecyc.com/share-ecommerce/applyComm/findThirdShopDetails'

    def __init__(self, batchNo=None, *args, **kwargs):
        super(FullSpider, self).__init__(batchNo=batchNo, *args, **kwargs)
        settings = get_project_settings()
        # 创建批次记录
        BatchDao().create_batch(self.batch_no)
        self.max_page_limit = 300
        self.authorization = 'eyJhbGciOiJIUzUxMiJ9.eyJyYW5kb20iOiIxNDYyNDAwNzk5NjM1MTQ4ODAyIiwiYWNjb3VudElkIjoiNjM0MjdjOTE1OTUzNGU2ZGExY2RjODJmYjMyNGNhMGEiLCJzdWIiOiI2MzQyN2M5MTU5NTM0ZTZkYTFjZGM4MmZiMzI0Y2EwYSIsImV4cCI6MTYzNzU4MTI5NSwiaWF0IjoxNjM3NDk4NDk1fQ.OG0bPNciJcHFSiA4oOx2wptWcNccFN4dtntqSjKbxc2jFe6bDYz5mNtjaB0nH-5PgW1czX1DER-GTwwkg-PE5A'
        self.item_helper = ItemHelper()
        self.goto_detail_page = settings.get('GOTO_DETAIL_PAGE', True)

    def _build_item_request(self, callback, no_match_sku):
        return Request(
            url=self.item_url,
            method='POST',
            meta={
                'reqType': 'item',
                'batchNo': self.batch_no,
                'skuId': no_match_sku.get('skuId'),
                'sku': copy.copy(no_match_sku),
            },
            headers={
                'Content-Type': 'application/json',
                'authorization': self.authorization
            },
            body=json.dumps({
                'sku': no_match_sku.get('supplierSkuId'),
                'proCode': no_match_sku.get('supplierId'),
            }),
            callback=callback,
            errback=self.error_back,
            priority=10,
        )

    def _build_list_request(self, callback, sp_name, sp_id, page=1, min_price=0, max_price=100000000):
        query = {
            'brandList': '',
            'cataId': '',
            'keyword': '',
            'maxPrice': '',
            'minPrice': '',
            'order': 'desc',
            'pageNo': page,
            'pageSize': 30,
            'proCodeList': [sp_id],
            'skuType': '',
            'sort': 'skuNum',
        }

        if min_price or min_price == 0:
            query['minPrice'] = min_price
        if max_price and max_price > min_price:
            query['maxPrice'] = max_price

        req = Request(
            method='POST',
            url=self.list_url,
            meta={
                'reqType': 'item',
                'batchNo': self.batch_no,
                'spId': sp_id,
                'spName': sp_name,
                'minPrice': min_price,
                'maxPrice': max_price,
                'page': page,

            },
            headers={
                'Content-Type': 'application/json',
                'authorization': self.authorization
            },
            body=json.dumps(query),
            callback=callback,
            errback=self.error_back,
            priority=20,
        )
        return req

    def start_requests(self):
        cookies = SeleniumLogin().get_cookies()
        # if not cookies or not cookies.get('token', ''):
        #     self.logger.error('init cookie failed...')
        #     return
        # self.authorization = cookies.get('token')
        # if not self.authorization:
        #     self.logger.error('no authorization...')
        #     return
        self.logger.info('init cookie: %s', cookies)
        pool_list = Mongo().list('supplier_pool', fields={'_id': 1, 'name': 1})
        self.logger.info('全量：%s' % (len(pool_list)))
        random.shuffle(pool_list)
        for sp in pool_list:
            sp_id = sp.get('_id')
            sp_name = sp.get('name')
            # 采第一页
            yield self._build_list_request(self.parse_sku_list, sp_name, sp_id)

    # 处理ItemData
    def parse_sku_list(self, response):
        meta = response.meta
        cur_page = meta.get('page')
        sp_id = meta.get('spId')
        sp_name = meta.get('spName')
        cur_min_price = meta.get('minPrice')
        cur_max_price = meta.get('maxPrice')

        data_list, no_match_list, total_page = parse_sku_list(response, self.item_helper)
        if data_list:
            self.logger.info('清单1: sp=%s, min=%s, max=%s, page=%s, cnt=%s' % (sp_id, cur_min_price, cur_max_price, cur_page, len(data_list)))
            yield Box('item', self.batch_no, data_list)
        # else:
        #     self.logger.error('空页: sp=%s, min=%s, max=%s, page=%s' % (sp_id, cur_min_price, cur_max_price, cur_page))

        # 分页逻辑
        if total_page and cur_page == 1 and total_page >= self.max_page_limit:
            if cur_min_price >= 0 and cur_max_price:
                half_list = half_split_int_range(cur_min_price, cur_max_price)
                if half_list and len(half_list) == 2:
                    # 上半部分
                    min_price_0, max_price_0 = half_list[0]
                    yield self._build_list_request(self.parse_sku_list, sp_name, sp_id, page=1, min_price=min_price_0, max_price=max_price_0)
                    # 下半部分
                    min_price_1, max_price_1 = half_list[1]
                    yield self._build_list_request(self.parse_sku_list, sp_name, sp_id, page=1, min_price=min_price_1, max_price=max_price_1)
                else:
                    self.logger.info('丢失: sp=%s, min=%s, max=%s' % (sp_id, cur_min_price, cur_max_price))
                    for page in range(2, total_page + 1):
                        yield self._build_list_request(self.parse_sku_list, sp_name, sp_id, page=page, min_price=cur_min_price, max_price=cur_max_price)
        else:
            for page in range(2, total_page + 1):
                yield self._build_list_request(self.parse_sku_list, sp_name, sp_id, page=page, min_price=cur_min_price, max_price=cur_max_price)

        # 补充商品信息
        if no_match_list:
            if self.goto_detail_page:
                for no_match_sku in no_match_list:
                    yield self._build_item_request(self.parse_item_data, no_match_sku)
            else:
                self.logger.info('清单2: sp=%s, min=%s, max=%s, page=%s, cnt=%s' % (sp_id, cur_min_price, cur_max_price, cur_page, len(no_match_list)))
                yield Box('item', self.batch_no, no_match_list)

    # 处理ItemData
    def parse_item_data(self, response):
        data = parse_item_data(response)
        self.logger.info('商品: [%s]' % data.get('skuId'))
        yield data
